package vip.xiaonuo.biz.modular.meetingreservation.service.impl;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import vip.xiaonuo.biz.modular.meetingreservation.entity.MeetingReservation;
import vip.xiaonuo.biz.modular.meetingreservation.service.MeetingReservationService;
import vip.xiaonuo.biz.modular.meetingreservation.service.MeetingReservationStatusService;
import vip.xiaonuo.common.cache.CommonCacheOperator;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;

/**
 * 会议室预约状态管理Service接口实现类
 *
 * @author 沐雨眠竹
 * @date  2025/05/15 10:05
 **/
@Slf4j
@Service
public class MeetingReservationStatusServiceImpl implements MeetingReservationStatusService {

    public static final String RESERVATION_END_TIME_PREFIX = "reservation-end-time";
    public static final String RESERVATION_DELAY_QUEUE = "reservation-delay-queue";

    @Resource
    private CommonCacheOperator commonCacheOperator;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private MeetingReservationService meetingReservationService;

    @Override
    public void setReservationEndTime(MeetingReservation meetingReservation) {
        try {
            // 解析预约日期和时间段，计算结束时间
            Date endTime = calculateEndTime(meetingReservation.getReservationDate(), meetingReservation.getTimeSlot());
            if (endTime == null) {
                return;
            }

            // 更新预约记录的实际结束时间
            meetingReservation.setActualEndTime(endTime);
            meetingReservationService.updateById(meetingReservation);

            // 计算从现在到结束时间的毫秒数
            long delayMillis = endTime.getTime() - System.currentTimeMillis();
            if (delayMillis <= 0) {
                // 如果已经过了结束时间，直接更新状态
                updateReservationStatus(meetingReservation.getId());
                return;
            }

            // 将预约ID添加到Redis延时队列中
            addToDelayQueue(meetingReservation.getId(), endTime.getTime());
        } catch (Exception e) {
            log.info("setReservationEndTime error:{}", e.getMessage());
        }
    }

    @Override
    public void addToDelayQueue(String reservationId, long execTime) {
        try {
            // 使用Redis的ZSet作为延时队列，分数为执行时间的时间戳
            stringRedisTemplate.opsForZSet().add(RESERVATION_DELAY_QUEUE, reservationId, execTime);

            // 同时在Redis中设置一个标记键，用于删除预约时能找到对应的队列项
            String endTimeKey = RESERVATION_END_TIME_PREFIX + ":" + reservationId;
            commonCacheOperator.put(endTimeKey, String.valueOf(execTime));
        } catch (Exception e) {
            log.info("addToDelayQueue error:{}", e.getMessage());
        }
    }

    @Override
    public Date calculateEndTime(String reservationDate, String timeSlot) {
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Date date = dateFormat.parse(reservationDate);

            //"09:00-10:00"
            String endTimeStr = timeSlot.split("-")[1].trim();
            SimpleDateFormat fullFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            return fullFormat.parse(dateFormat.format(date) + " " + endTimeStr + ":00");
        } catch (ParseException | ArrayIndexOutOfBoundsException e) {
            log.info("calculateEndTime error:{}", e.getMessage());
            return null;
        }
    }

    @Override
    public void updateReservationStatus(String reservationId) {
        try {
            MeetingReservation reservation = meetingReservationService.getById(reservationId);
            if (reservation != null && "已批准".equals(reservation.getStatus())) {
                reservation.setStatus("已完成");
                meetingReservationService.updateById(reservation);
            }

            // 更新状态后，从延时队列中移除
            removeFromDelayQueue(reservationId);
        } catch (Exception e) {
            log.info("updateReservationStatus error:{}", e.getMessage());
        }
    }

    @Override
    public void removeFromDelayQueue(String reservationId) {
        try {
            stringRedisTemplate.opsForZSet().remove(RESERVATION_DELAY_QUEUE, reservationId);
            String endTimeKey = RESERVATION_END_TIME_PREFIX + ":" + reservationId;
            commonCacheOperator.remove(endTimeKey);
        } catch (Exception e) {
            log.info("removeFromDelayQueue error:{}", e.getMessage());
        }
    }

    @Override
    public void processDelayQueue() {
        try {
            // 获取当前时间戳
            long now = System.currentTimeMillis();

            // 查询所有已到期的任务（分数小于等于当前时间戳的所有成员）
            Set<String> expiredTasks = stringRedisTemplate.opsForZSet().rangeByScore(
                    RESERVATION_DELAY_QUEUE, 0, now);

            if (expiredTasks != null && !expiredTasks.isEmpty()) {
                for (String reservationId : expiredTasks) {
                    // 更新预约状态
                    updateReservationStatus(reservationId);
                }
            }
        } catch (Exception e) {
            log.info("processDelayQueue error:{}", e.getMessage());
        }
    }
}
